import { ModelType, MODEL_CAPABILITIES, ModelCapabilities } from '@/types/models';

export type TaskType = 'creative' | 'technical' | 'analysis' | 'translation' | 
                       'code' | 'chinese_content' | 'long_context' | 'general';

export interface RecommendationCriteria {
  taskType: TaskType;
  language?: string;
  maxTokens?: number;
  optimizeFor?: 'quality' | 'cost' | 'speed';
  requiredFeatures?: string[];
}

export interface ModelRecommendation {
  model: ModelType;
  score: number;
  reasons: string[];
  matchedFeatures: string[];
  warnings?: string[];
}

class ModelRecommendationService {
  private taskTypeMapping: Record<TaskType, string[]> = {
    creative: ['creative', 'general'],
    technical: ['technical', 'code', 'math'],
    analysis: ['analysis', 'reasoning', 'long_context'],
    translation: ['general', 'multilingual'],
    code: ['code', 'technical', 'math'],
    chinese_content: ['chinese_content', 'creative'],
    long_context: ['long_context', 'research'],
    general: ['general', 'conversation']
  };

  private languagePriority: Record<string, number> = {
    zh: 3,  // Chinese
    en: 2,  // English
    ja: 1,  // Japanese
    ko: 1   // Korean
  };

  /**
   * Get model recommendations based on criteria
   */
  public getRecommendations(criteria: RecommendationCriteria): ModelRecommendation[] {
    const recommendations: ModelRecommendation[] = [];

    Object.entries(MODEL_CAPABILITIES).forEach(([modelKey, capabilities]) => {
      const model = modelKey as ModelType;
      const recommendation = this.evaluateModel(model, capabilities, criteria);
      if (recommendation.score > 0) {
        recommendations.push(recommendation);
      }
    });

    // Sort by score descending
    recommendations.sort((a, b) => b.score - a.score);

    // Add relative positioning reasons for top recommendations
    if (recommendations.length > 0) {
      const topScore = recommendations[0].score;
      recommendations.forEach((rec, index) => {
        if (index === 0) {
          rec.reasons.unshift('✨ 最佳匹配');
        } else if (rec.score >= topScore * 0.9) {
          rec.reasons.unshift('👍 高度匹配');
        } else if (rec.score >= topScore * 0.7) {
          rec.reasons.unshift('✓ 适合');
        }
      });
    }

    return recommendations.slice(0, 5); // Return top 5 recommendations
  }

  /**
   * Evaluate a single model against criteria
   */
  private evaluateModel(
    model: ModelType,
    capabilities: ModelCapabilities,
    criteria: RecommendationCriteria
  ): ModelRecommendation {
    let score = 0;
    const reasons: string[] = [];
    const matchedFeatures: string[] = [];
    const warnings: string[] = [];

    // 1. Task type matching (40% weight)
    const taskSpecialties = this.taskTypeMapping[criteria.taskType] || [];
    const matchedSpecialties = taskSpecialties.filter(spec => 
      capabilities.specialties.includes(spec)
    );
    
    if (matchedSpecialties.length > 0) {
      score += 40 * (matchedSpecialties.length / taskSpecialties.length);
      matchedFeatures.push(...matchedSpecialties);
      reasons.push(`擅长${this.getTaskTypeDescription(criteria.taskType)}`);
    }

    // 2. Language support (20% weight)
    if (criteria.language) {
      if (capabilities.languages.includes(criteria.language)) {
        const langScore = 20;
        score += langScore;
        reasons.push(`支持${this.getLanguageDescription(criteria.language)}`);
      } else {
        warnings.push(`不支持${this.getLanguageDescription(criteria.language)}`);
      }
    }

    // 3. Token limit check (20% weight)
    if (criteria.maxTokens) {
      if (capabilities.maxTokens >= criteria.maxTokens) {
        score += 20;
        reasons.push(`支持${criteria.maxTokens} tokens`);
      } else {
        const ratio = capabilities.maxTokens / criteria.maxTokens;
        score += 20 * ratio;
        if (ratio < 0.8) {
          warnings.push(`最大仅支持${capabilities.maxTokens} tokens`);
        }
      }
    } else {
      score += 20; // Full score if no token requirement
    }

    // 4. Optimization preference (20% weight)
    if (criteria.optimizeFor) {
      switch (criteria.optimizeFor) {
        case 'quality':
          // Prefer more expensive, slower models
          if (model === ModelType.GPT4 || model === ModelType.CLAUDE) {
            score += 20;
            reasons.push('高质量输出');
          } else {
            score += 10;
          }
          break;
        
        case 'cost':
          // Prefer cheaper models
          const costScore = 20 * (1 - capabilities.costPerToken / 0.00003);
          score += Math.max(0, costScore);
          if (capabilities.costPerToken <= 0.00001) {
            reasons.push('成本效益高');
          }
          break;
        
        case 'speed':
          // Prefer faster models
          if (capabilities.responseTime === 'fast') {
            score += 20;
            reasons.push('响应速度快');
          } else if (capabilities.responseTime === 'medium') {
            score += 10;
          } else {
            score += 5;
          }
          break;
      }
    } else {
      score += 10; // Default score
    }

    // 5. Special features matching
    if (criteria.requiredFeatures) {
      const matchedReqFeatures = criteria.requiredFeatures.filter(feature =>
        capabilities.specialties.includes(feature)
      );
      if (matchedReqFeatures.length > 0) {
        score += 10 * (matchedReqFeatures.length / criteria.requiredFeatures.length);
        matchedFeatures.push(...matchedReqFeatures);
      }
    }

    // Add model-specific bonuses
    score += this.getModelSpecificBonus(model, criteria);

    return {
      model,
      score: Math.min(100, score), // Cap at 100
      reasons,
      matchedFeatures,
      warnings: warnings.length > 0 ? warnings : undefined
    };
  }

  /**
   * Get model-specific bonuses based on special capabilities
   */
  private getModelSpecificBonus(model: ModelType, criteria: RecommendationCriteria): number {
    let bonus = 0;

    switch (model) {
      case ModelType.KIMI:
        if (criteria.maxTokens && criteria.maxTokens > 10000) {
          bonus += 10;
        }
        break;
      
      case ModelType.DEEPSEEK:
        if (criteria.taskType === 'code' || criteria.taskType === 'technical') {
          bonus += 5;
        }
        break;
      
      case ModelType.QWEN:
      case ModelType.ERNIE:
        if (criteria.language === 'zh') {
          bonus += 5;
        }
        break;
      
      case ModelType.CLAUDE:
        if (criteria.taskType === 'analysis') {
          bonus += 5;
        }
        break;
    }

    return bonus;
  }

  /**
   * Get task type description in Chinese
   */
  private getTaskTypeDescription(taskType: TaskType): string {
    const descriptions: Record<TaskType, string> = {
      creative: '创意写作',
      technical: '技术文档',
      analysis: '深度分析',
      translation: '翻译',
      code: '代码生成',
      chinese_content: '中文内容',
      long_context: '长文本处理',
      general: '通用对话'
    };
    return descriptions[taskType] || taskType;
  }

  /**
   * Get language description
   */
  private getLanguageDescription(language: string): string {
    const descriptions: Record<string, string> = {
      zh: '中文',
      en: '英文',
      ja: '日文',
      ko: '韩文'
    };
    return descriptions[language] || language;
  }

  /**
   * Get quick recommendation based on user input
   */
  public getQuickRecommendation(userInput: string): ModelRecommendation[] {
    // Analyze user input to determine task type
    const taskType = this.inferTaskType(userInput);
    const language = this.detectLanguage(userInput);
    const estimatedTokens = this.estimateTokens(userInput);

    return this.getRecommendations({
      taskType,
      language,
      maxTokens: estimatedTokens,
      optimizeFor: 'quality' // Default to quality
    });
  }

  /**
   * Infer task type from user input
   */
  private inferTaskType(input: string): TaskType {
    const lowerInput = input.toLowerCase();

    // Check for code-related keywords
    if (/代码|code|编程|function|class|debug|程序/.test(lowerInput)) {
      return 'code';
    }

    // Check for creative writing keywords
    if (/故事|小说|创意|创作|诗|文章|story|creative/.test(lowerInput)) {
      return 'creative';
    }

    // Check for analysis keywords
    if (/分析|解析|研究|深度|原因|为什么|analyze|research/.test(lowerInput)) {
      return 'analysis';
    }

    // Check for technical keywords
    if (/技术|文档|说明|api|架构|technical|document/.test(lowerInput)) {
      return 'technical';
    }

    // Check for translation
    if (/翻译|translate|translation/.test(lowerInput)) {
      return 'translation';
    }

    // Check for Chinese content
    if (/[\u4e00-\u9fa5]{10,}/.test(input)) {
      return 'chinese_content';
    }

    // Long input suggests long context processing
    if (input.length > 1000) {
      return 'long_context';
    }

    return 'general';
  }

  /**
   * Detect language from user input
   */
  private detectLanguage(input: string): string {
    // Simple language detection based on character sets
    if (/[\u4e00-\u9fa5]/.test(input)) {
      return 'zh';
    }
    if (/[\u3040-\u309f\u30a0-\u30ff]/.test(input)) {
      return 'ja';
    }
    if (/[\uac00-\ud7af]/.test(input)) {
      return 'ko';
    }
    return 'en';
  }

  /**
   * Estimate required tokens based on input
   */
  private estimateTokens(input: string): number {
    // Rough estimation: 1 token ≈ 0.75 English words ≈ 0.5 Chinese characters
    const chineseChars = (input.match(/[\u4e00-\u9fa5]/g) || []).length;
    const englishWords = input.split(/\s+/).length;
    
    const estimatedInputTokens = chineseChars * 2 + englishWords * 1.3;
    // Assume output will be 2-3x the input
    const estimatedOutputTokens = estimatedInputTokens * 2.5;
    
    return Math.min(8000, Math.ceil(estimatedInputTokens + estimatedOutputTokens));
  }

  /**
   * Get user feedback and update recommendations
   */
  public recordFeedback(
    model: ModelType,
    taskType: TaskType,
    satisfaction: 'good' | 'bad'
  ): void {
    // TODO: Implement feedback storage and learning
    // This could be used to improve recommendations over time
    console.log(`Feedback recorded: ${model} for ${taskType} was ${satisfaction}`);
  }
}

export const modelRecommendationService = new ModelRecommendationService();